package com.pine.dbant.common.plugin.meta.function.jdbc;

import com.google.common.collect.Lists;
import com.pine.dbant.common.plugin.meta.*;
import lombok.extern.slf4j.Slf4j;

import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author xiaoyuan
 * @create 2022/12/30 11:18
 **/
@Slf4j
public class FunctionsFunction extends AbstractQueryMetadataFunction <JdbcMetadataAnalysisConfig,List> {

    public FunctionsFunction(String type) {
        super(type);
    }

    @Override
    public List<MetadataNode> doQuery(JdbcMetadataAnalysisConfig metadataAnalysisConfig, QueryMetadataParam queryMetadataParam) {
        DatabaseMetaData dbMetaData;
        try {
            dbMetaData = metadataAnalysisConfig.getConnection().getMetaData();
        } catch (SQLException e) {
            throw new JdbcMetaAnalysisException(e.getMessage(), e);
        }
        String catalog = queryMetadataParam.getConfiguration().getNecessaryValue("catalog");
        List<Map<String, Object>> functions = getFunctions(dbMetaData, catalog, null);
        return null;
    }

    public List<Map<String, Object>> getFunctions(DatabaseMetaData dbMetaData, String catalog, String schemaName) {
        List<Map<String, Object>> functions = Lists.newArrayList();
        /**
         * catalog : 类别名称，因为存储在此数据库中，所以它必须匹配类别名称。该参数为 “” 则检索没有类别的描述，为 null 则表示该类别名称不应用于缩小搜索范围
         * schema : 模式名称，因为存储在此数据库中，所以它必须匹配模式名称。该参数为 “” 则检索那些没有模式的描述，为 null 则表示该模式名称不应用于缩小搜索范围
         * table : 表名称，因为存储在此数据库中，所以它必须匹配表名称
         * unique : 该参数为 true 时，仅返回惟一值的索引；该参数为 false 时，返回所有索引，不管它们是否惟一
         * approximate : 该参数为 true 时，允许结果是接近的数据值或这些数据值以外的值；该参数为 false 时，要求结果是精确结果
         */
        try (ResultSet rs = dbMetaData.getFunctions(catalog, schemaName, null)) {
            ResultSetMetaData fkmd = rs.getMetaData();
            Map<String, Object> map;
            while (rs.next()) {
                map = new HashMap<>();
                for (int i = 1; i <= fkmd.getColumnCount(); i++) {
                    map.put(fkmd.getColumnName(i), rs.getObject(i));
                }
            }
        } catch (SQLException e) {
            log.error("获取数据库[{}]下schema[{}]的外键信息错误", catalog, schemaName, e);
            //此处错误不往上抛，主要原因是有些驱动不支持查询，需要自己在实现类中通过sql自己查询
        }
        return functions;
    }
}
